package org.dxy.domain.model.aggregate.impl;

import lombok.Builder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.dxy.domain.command.product.*;
import org.dxy.domain.event.DomainEvent;
import org.dxy.domain.event.product.*;
import org.dxy.domain.model.aggregate.Product;
import org.dxy.domain.model.valobj.ProductId;
import org.dxy.domain.model.valobj.ProductStatusEnum;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @description: 产品聚合根实现类
 * @author: dxy
 * @createTime: 2025/8/17
 */
@Slf4j
@Getter
@Builder
public class ProductAggRoot implements Product {
    /** 产品ID */
    private ProductId productId;
    /** 产品编码 */
    private String productCode;
    /** 产品名称 */
    private String productName;
    /** 产品规格 */
    private String specification;
    /** 产品版本 */
    private String version;
    /** 产品状态 */
    private ProductStatusEnum status;
    /** 关联的工艺路线ID */
    private Long routeId;

    private final List<DomainEvent> domainEvents = new ArrayList<>();

    // === 静态工厂方法 ===
    public static Product create(Long productId, CreateProductCommand command) {
        ProductAggRoot product = ProductAggRoot.builder()
                .productId(ProductId.of(productId))
                .productCode(command.productCode())
                .productName(command.productName())
                .version(command.version())
                .status(ProductStatusEnum.CREATED)
                .build();

        ProductCreatedEvent event = new ProductCreatedEvent(
                productId,
                command.productCode(),
                command.type(),
                command.version(),
                command.unit(),
                command.bom()
        );
        product.addDomainEvent(event);

        return product;
    }

    // === 事件相关方法 ===
    @Override
    public List<DomainEvent> getDomainEvents() {
        return Collections.unmodifiableList(domainEvents);
    }

    @Override
    public void addDomainEvent(DomainEvent event) {
        domainEvents.add(event);
    }

    @Override
    public void clearDomainEvents() {
        domainEvents.clear();
    }

    @Override
    public boolean hasDomainEvents() {
        return !domainEvents.isEmpty();
    }

    @Override
    public boolean hasNoDomainEvents() {
        return domainEvents.isEmpty();
    }

    // === 业务方法 ===
    @Override
    public void update(UpdateProductCommand command) {
        checkNotDeleted();
        this.productName = command.productName();
        this.version = command.version();

        ProductUpdatedEvent event = new ProductUpdatedEvent(
                productId.getValue(),
                command.productName(),
                command.type(),
                command.version(),
                command.unit(),
                command.bom()  // 这里是 Bom 对象
        );
        addDomainEvent(event);
    }

    @Override
    public void enable(EnableProductCommand command) {
        checkNotDeleted();
        if (status == ProductStatusEnum.ENABLED) {
            throw new IllegalStateException("产品已经处于启用状态");
        }
        this.status = ProductStatusEnum.ENABLED;
        addDomainEvent(new ProductEnabledEvent(productId.getValue()));
    }

    @Override
    public void disable(DisableProductCommand command) {
        checkNotDeleted();
        if (status == ProductStatusEnum.DISABLED) {
            throw new IllegalStateException("产品已经处于禁用状态");
        }
        this.status = ProductStatusEnum.DISABLED;
        addDomainEvent(new ProductDisabledEvent(productId.getValue()));
    }

    @Override
    public void delete(DeleteProductCommand command) {
        // 检查是否可以删除
        if (!canDelete()) {
            throw new IllegalStateException("当前状态的产品不能删除，只有已创建、已禁用状态的产品可以删除");
        }
        
        log.info("删除产品: productId={}, status={}", productId.getValue(), status);
        
        this.status = ProductStatusEnum.DELETED;
        addDomainEvent(new ProductDeletedEvent(productId.getValue()));
    }

    @Override
    public void changeVersion(ChangeProductVersionCommand command) {
        checkNotDeleted();
        if (command.newVersion().equals(this.version)) {
            throw new IllegalArgumentException("新版本号与当前版本号相同");
        }
        this.version = command.newVersion();
        addDomainEvent(new ProductVersionChangedEvent(productId.getValue(), command.newVersion()));
    }

    @Override
    public void updateBOM(UpdateProductBOMCommand command) {
        checkNotDeleted();
        addDomainEvent(new ProductBOMUpdatedEvent(productId.getValue()));
    }

    @Override
    public void assignRoute(AssignProductRouteCommand command) {
        checkNotDeleted();
        if (this.routeId != null && this.routeId.equals(command.routeId())) {
            throw new IllegalArgumentException("产品已经分配了该工艺路线");
        }
        this.routeId = command.routeId();
        addDomainEvent(new ProductRouteAssignedEvent(productId.getValue(), command.routeId()));
    }

    @Override
    public void unassignRoute(UnassignProductRouteCommand command) {
        checkNotDeleted();
        if (this.routeId == null || !this.routeId.equals(command.routeId())) {
            throw new IllegalArgumentException("产品未分配该工艺路线");
        }
        this.routeId = null;
        addDomainEvent(new ProductRouteUnassignedEvent(productId.getValue(), command.routeId()));
    }

    @Override
    public void approve(ApproveProductCommand command) {
        checkNotDeleted();
        if (status == ProductStatusEnum.APPROVED) {
            throw new IllegalStateException("产品已经审核通过");
        }
        this.status = ProductStatusEnum.APPROVED;
        addDomainEvent(new ProductApprovedEvent(productId.getValue()));
    }

    @Override
    public void reject(RejectProductCommand command) {
        checkNotDeleted();
        if (status == ProductStatusEnum.REJECTED) {
            throw new IllegalStateException("产品已经被驳回");
        }
        this.status = ProductStatusEnum.REJECTED;
        addDomainEvent(new ProductRejectedEvent(productId.getValue(), command.reason()));
    }

    /**
     * 检查产品是否可以删除
     */
    private boolean canDelete() {
        return status == ProductStatusEnum.CREATED || 
               status == ProductStatusEnum.DISABLED;
    }

    /**
     * 检查产品是否已删除
     */
    private void checkNotDeleted() {
        if (status == ProductStatusEnum.DELETED) {
            throw new IllegalStateException("产品已删除，不能进行操作");
        }
    }
}